package com.linkgie.galaxyframework.crypto;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import com.linkgie.galaxyframework.utils.BinaryUtils;

/**
 * 密码学摘要生成器；
 * <p>
 * 
 * 支持对连续数据进行操作的功能；
 * 
 * @author liso
 *
 * @param <T>
 */
public interface CryptoDigester<T> extends CryptoComponent {

	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(byte[] data) {
		update(data, 0, data.length);
		
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(long data) {
		byte[] bytesData = BinaryUtils.toBytes(data);
		update(bytesData, 0, bytesData.length);
		
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(int data) {
		byte[] bytesData = BinaryUtils.toBytes(data);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(short data) {
		byte[] bytesData = BinaryUtils.toBytes(data);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(char data) {
		byte[] bytesData = BinaryUtils.toBytes(data);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(boolean data) {
		byte[] bytesData = BinaryUtils.toBytes(data);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(float data) {
		byte[] bytesData = BinaryUtils.toBytes(data);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(double data) {
		byte[] bytesData = BinaryUtils.toBytes(data);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(String data) {
		byte[] bytesData = BinaryUtils.toBytes_UTF8(data);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(String data, String charset) {
		byte[] bytesData = BinaryUtils.toBytes(data, charset);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(String data, Charset charset) {
		byte[] bytesData = BinaryUtils.toBytes(data,charset);
		update(bytesData, 0, bytesData.length);
		return this;
	}
	
	/**
	 * 追加数据；
	 * 
	 * @param data
	 */
	default CryptoDigester<T> update(byte data) {
		update(new byte[]{data}, 0, 1);
		return this;
	}

	/**
	 * 追加数据；
	 * 
	 * @param data
	 * @param offset
	 * @param length
	 * @throws IOException
	 */
	default CryptoDigester<T> update(InputStream in) {
		byte[] buff = new byte[4096];
		int len = 0;
		try {
			while ((len = in.read(buff)) > 0) {
				update(buff, 0, len);
			}
			return this;
		} catch (IOException e) {
			throw new IllegalStateException(e.getMessage(), e);
		}
	}

	/**
	 * 追加数据；
	 * 
	 * @param data
	 * @param offset
	 * @param length
	 */
	CryptoDigester<T> update(byte[] data, int offset, int length);

	/**
	 * 完成操作；
	 * 
	 * @return
	 */
	T doFinal();
}
